﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Reflection;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Net;
using System.Collections.Specialized;

namespace YWTSSys.Library
{
    public static class RequestHelper
    {

        private static T GetRequestValue<T>(string name, bool useDefValue, T defValue)
        {
            string str = HttpContext.Current.Request[name];
            T value= default(T);

            if (string.IsNullOrEmpty(str))
            {
                if (useDefValue) return defValue;

                throw new ArgumentNullException(name);
            }

            str = HttpContext.Current.Server.UrlDecode(str);
            try
            {
                Type type = typeof(T);

                if (type.IsEnum)
                {
                    value = (T)Enum.Parse(type, str);
                }
                else
                {
                    value = (T)Convert.ChangeType(str, type);
                }
            }
            catch//(Exception err)
            {
                // throw new ArgumentOutOfRangeException(name);
            }
            return value;
        }

        #region 获取查询字符串或Html控件的值

        public static T GetRequestValue<T>(this HttpRequest r, string name)
        {
            return GetRequestValue<T>(name, true, default(T));
        }

        public static T GetRequestValue<T>(this HttpRequest t,string name, bool useDefValue, T defValue)
        {
            return GetRequestValue<T>(name, useDefValue, defValue);
        }

        /// <summary>
        /// 获取查询字符串或Html控件的值，若数据类型转化失败，则返回 T 的指定默认值 
        /// （注：当获取的是Html控件的值时，若控件设置了disable属性为disabled时，不能获取控件的值）
        /// </summary>
        /// <typeparam name="T">数据类型参数</typeparam>
        /// <param name="param">查询字符串参数或Html控件名</param>
        /// <param name="defaultValue">指定的默认值</param>
        /// <param name="isRequestForm">是否为表单参数(true:获取Html控件的值，false:获取查询字符串的值)</param>
        /// <returns>返查询字符串或Html控件的值</returns>
        public static T Request<T>(string param, T defaultValue, bool isRequestForm)
        {
            string RequestStr = "";
            if (!isRequestForm)
            {
                RequestStr = HttpContext.Current.Request.QueryString[param];
            }
            else
            {
                RequestStr = HttpContext.Current.Request.Form[param];
            }

            if (RequestStr != null)
            {
                try
                {
                    return (T)System.Convert.ChangeType(RequestStr, typeof(T));
                }
                catch
                {
                    return defaultValue;
                }
            }
            else
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// 获取查询字符串的值，若数据类型转化失败，则返回 T 的指定默认值 
        /// </summary>
        /// <typeparam name="T">数据类型参数</typeparam>
        /// <param name="param">查询字符串参数</param>
        /// <param name="defaultValue">T 的指定默认值</param>
        /// <returns>查询字符串的值</returns>
        public static T Request<T>(string param, T defaultValue)
        {
            return Request<T>(param, defaultValue, false);
        }

        /// <summary>
        /// 获取查询字符串的值，若数据类型转化失败，则返回 T 的默认值
        /// </summary>
        /// <typeparam name="T">数据类型参数</typeparam>
        /// <param name="param">查询字符串参数</param>
        /// <returns>查询字符串的值</returns>
        public static T Request<T>(string param)
        {
            return Request<T>(param, default(T), false);
        }

        #endregion

        /// <summary>
        /// 内容：检测当前请求来源是否来自本服务器
        /// 新增日期:2010-04-20
        /// 作者：李文瀚
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static bool CheckRequstOrigin(this HttpRequest request)
        {
            //HttpRequest request = HttpContext.Current.Request;
            string userIp = request.UserHostAddress;

            if (userIp == "127.0.0.1" || userIp == "localhost" || userIp == "::1")
                return true;
            string strhostname = Dns.GetHostName();
            System.Net.IPHostEntry ip = Dns.GetHostByName(strhostname);
            foreach (System.Net.IPAddress ipA in ip.AddressList)
            {
                if (userIp == ipA.ToString().ToLower().Trim())
                    return true;

            }
            return false;
        }
        /// <summary>
        /// 判断用户请求是否是内容还是外网
        /// false是外网
        /// true是内网
        /// </summary>
        /// <returns></returns>
        public static bool GetUserRequstSoure(this HttpRequest Request)
        {
            //string user_IP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            //return user_IP;
           // HttpRequest Request = HttpContext.Current.Request;
            string _userIP;
            if (Request.ServerVariables["HTTP_VIA"] == null)//未使用代理
            {
                _userIP = Request.UserHostAddress;
            }
            else//使用代理服务器
            {
                _userIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            }
            if (_userIP == "127.0.0.1" || _userIP == "localhost" || _userIP == "::1")
                return true;

            if (_userIP.Contains("192.168"))
                return true;

            return false;
        }

        private static bool IsNumeric(object Expression)
        {
            bool isNum;
            double retNum;
            isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
            return isNum;
        }
        /// <summary>
        /// 从当前请求中提取类型T,如果不存在,则返回一个new T();
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static T SerializableObject<T>(this HttpRequest source) where T : new()
        {
            object objObject = Activator.CreateInstance(typeof(T));
            PropertyInfo[] ps = objObject.GetType().GetProperties();

            PropertyInfo objPropertyInfo = null;
            Type objPropertyType = null;
            object objDataValue = null;
            Type objDataType = default(Type);
            for (int i = 0; i < ps.Length; i++)
            {
                //PropertyInfo item = ps[i];
                //item.SetValue(obj, string.IsNullOrEmpty(source[item.Name]) ? item.GetValue(obj, null) : source[item.Name], null);



                //If the Column matches a Property in the Object Map's PropertyInfo Dictionary 
                if (true)
                {
                    objPropertyInfo = ps[i];
                    //Get its type 
                    objPropertyType = objPropertyInfo.PropertyType;

                    //If property can be set 
                    if (objPropertyInfo.CanWrite)
                    {
                        //Get the Data Value from the data reader 

                        if (string.IsNullOrEmpty(source[objPropertyInfo.Name]))
                            continue;
                        objDataValue = HttpUtility.HtmlEncode(source[objPropertyInfo.Name]);
                        //Get the Data Value's type 
                        objDataType = objDataValue.GetType();

                        if (objDataValue == System.DBNull.Value)
                        {
                            // set property value to Null 
                            objPropertyInfo.SetValue(objObject, Null.SetNull(objPropertyInfo), null);
                        }
                        else if (objPropertyType.Equals(objDataType))
                        {
                            //Property and data objects are the same type 
                            objPropertyInfo.SetValue(objObject, objDataValue, null);
                        }
                        else
                        {
                            // business object info class member data type does not match datareader member data type 
                            try
                            {
                                //need to handle enumeration conversions differently than other base types 
                                if (objPropertyType.BaseType.Equals(typeof(System.Enum)))
                                {
                                    // check if value is numeric and if not convert to integer ( supports databases like Oracle ) 
                                    if (IsNumeric(objDataValue))
                                    {
                                        objPropertyInfo.SetValue(objObject, System.Enum.ToObject(objPropertyType, Convert.ToInt32(objDataValue)), null);
                                    }
                                    else
                                    {
                                        objPropertyInfo.SetValue(objObject, System.Enum.ToObject(objPropertyType, objDataValue), null);
                                    }
                                }
                                else if (objPropertyType.FullName.Equals("System.Guid"))
                                {
                                    // guid is not a datatype common across all databases ( ie. Oracle ) 
                                    objPropertyInfo.SetValue(objObject, Convert.ChangeType(new Guid(objDataValue.ToString()), objPropertyType), null);
                                }
                                else if (objPropertyType.FullName.Equals("System.Version"))
                                {
                                    objPropertyInfo.SetValue(objObject, new Version(objDataValue.ToString()), null);
                                }
                                else
                                {
                                    // try explicit conversion 
                                    objPropertyInfo.SetValue(objObject, objDataValue, null);
                                }
                            }
                            catch
                            {
                                objPropertyInfo.SetValue(objObject, Convert.ChangeType(objDataValue, objPropertyType), null);
                            }
                        }
                    }
                }
            }
            return (T)objObject;
        }
        /// <summary>
        /// 将当前请求中类型T序列化为XML格式,如果不存在则返回空
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static string SerializableToXml<T>(this HttpRequest source) where T : new()
        {
            T obj = SerializableObject<T>(source);

            return obj.SerializableToXml();

            //System.Text.Encoding encoding = System.Text.ASCIIEncoding.UTF8;
            //XmlSerializer XMLSerializer = new XmlSerializer(obj.GetType());
            //using (MemoryStream memoryStream = new MemoryStream())
            //{
            //    XmlTextWriter XMLWriter = new XmlTextWriter(memoryStream, encoding);
            //    XMLSerializer.Serialize(XMLWriter, obj);
            //    string result = encoding.GetString(memoryStream.ToArray()).Trim();
            //    XMLWriter.Close();
            //    memoryStream.Close();
            //    return result;
            //}
            //return "";
        }

        /// <summary>
        /// 将可系列化的对象序列化为XML格式字符串返回
        /// 注意:
        /// 如果字段的类型不是string类型,那么在转换为XML时.会自动使用此类型的默认值做为xml节点的的值.
        /// 如
        /// int类型使用0,
        /// datetime使用0001-01-01
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string SerializableToXml(this Object obj)
        {
            string result = "";
            System.Text.Encoding encoding = System.Text.ASCIIEncoding.GetEncoding("GB2312");
            XmlSerializer XMLSerializer = new XmlSerializer(obj.GetType());
            using (MemoryStream memoryStream = new MemoryStream())
            {
                XmlTextWriter XMLWriter = new XmlTextWriter(memoryStream, encoding);
                XMLSerializer.Serialize(XMLWriter, obj);
                result = encoding.GetString(memoryStream.ToArray()).Trim();
                XMLWriter.Close();
                memoryStream.Close();
            }

            return result.Replace("encoding=\"gb2312\"", "");
        }
    }
}
